#include<windows.h>
#include "BasicPad.h"

namespace PadGui
{
	struct threadSynObject
	{
		BasicPad *pad;
		HANDLE Event;
	};





	LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
	{

		if(message == WM_NCCREATE)
		{
			 BasicPad *pad =  (BasicPad*)(((LPCREATESTRUCT) lParam)->lpCreateParams);
			 SetWindowLongW(hWnd,GWL_USERDATA, (LONG)pad);
			 return pad->WndProc((long)hWnd,message,wParam,lParam);
		}

		BasicPad *pad = (BasicPad *)GetWindowLong(hWnd,GWL_USERDATA);
		return pad->WndProc((long)hWnd,message,wParam,lParam);
	
	}





	DWORD WINAPI ThreadProc(LPVOID lpParameter)
	{
		threadSynObject *obj = (threadSynObject*)lpParameter;

		MSG msg;
		HWND hWnd;
		wchar_t szWindowClass[]= L"BasicPad";                               
		WNDCLASSEXW wcex={0};
		wcex.cbSize = sizeof(WNDCLASSEXW);       
		wcex.style            = CS_HREDRAW | CS_VREDRAW;   
		wcex.lpfnWndProc    = (WNDPROC)WndProc;            
		wcex.hInstance        = 0;        
		wcex.hbrBackground    = (HBRUSH)COLOR_WINDOWFRAME;   
		wcex.lpszClassName    = szWindowClass;       
		wcex.hIcon            =0;     
		wcex.hCursor        =LoadCursor(NULL, IDC_ARROW);       
		wcex.lpszMenuName    =0;       
		wcex.hIconSm        =0;        
		RegisterClassExW(&wcex);           
		

		hWnd = CreateWindowExW(WS_EX_LAYERED|WS_EX_TOOLWINDOW,szWindowClass,NULL,WS_VISIBLE|WS_POPUP,200,200,400,300,NULL,NULL,NULL,obj->pad);

		if (!hWnd){
		  return FALSE;
		}

		SetLayeredWindowAttributes(hWnd,0, 100, LWA_ALPHA);
		//SetWindowLongW(hWnd,GWL_USERDATA, (LONG)obj->pad); 
		obj->pad->HWnd((long)hWnd);

		ShowWindow(hWnd, SW_HIDE);
		UpdateWindow(hWnd);
		SetEvent(obj->Event);
		while (GetMessage(&msg, NULL, 0, 0))    
		{
			TranslateMessage(&msg);        
			DispatchMessage(&msg);        
		}

		return msg.wParam;
	}









	 BasicPad::BasicPad()
	{
		this->message = new wstring();
		threadSynObject *obj = new threadSynObject();
		obj->pad = this;
		obj->Event = CreateEventW(NULL,true,false,NULL);
		CreateThread(NULL,0,ThreadProc,obj,0,NULL);// set obj point to the function ThreadProc.
		WaitForSingleObject(obj->Event,-1); // waiting forever
		CloseHandle(obj->Event);
		delete obj;
	}

	 BasicPad::~BasicPad()
	{
		delete this->message;
		this->message = 0;

		if(IsWindow((HWND)this->HWnd()))
		{
			DestroyWindow((HWND)this->HWnd());
		}
	}





	 void BasicPad::Show()
	{
		ShowWindow((HWND)this->HWnd() ,SW_SHOW);
	}




	 void BasicPad::Hide()
	{
		ShowWindow((HWND)this->hWnd ,SW_HIDE);
	}










	void BasicPad::HWnd(long int hwnd)
	{
		this->hWnd = hwnd;
	}


	unsigned long BasicPad::WndProc(long hWnd,unsigned long message,unsigned long wParam,unsigned long lParam)
	{
		
		switch (message) 
		{    
			case WM_PAINT:   
				if(this->Message().length() > 0 )
				{
					HDC hdc;
					RECT rect;
					PAINTSTRUCT ps;
					hdc = BeginPaint((HWND)hWnd, &ps);
					GetClientRect((HWND)hWnd, &rect);
					DrawTextW(hdc, (this->Message()) .c_str() , (this->Message()).length() , &rect, DT_EDITCONTROL|DT_WORDBREAK|DT_NOPREFIX);
					EndPaint((HWND)hWnd, &ps);
				}
				break;
			case WM_DESTROY:    
				PostQuitMessage(0);
				break;
			default:
				return DefWindowProc((HWND)hWnd, message, wParam, lParam);
	   }
	   return 0;
	}



 };